#include <iostream>
#include <string>
#include <thread> // For sleep
#include <mqtt/async_client.h>

const int QOS = 1;
const std::string SERVER_ADDRESS("tcp://localhost:1883");
const std::string CLIENT_ID("example_client");
const std::string TOPIC("test/topic");

class callback : public virtual mqtt::callback, public virtual mqtt::iaction_listener
{
private:
    mqtt::async_client &client_;

public:
    callback(mqtt::async_client &client) : client_(client) {}

    void connection_lost(const std::string &cause) override
    {
        std::cout << "Connection lost " << std::endl;
        if (!cause.empty())
            std::cout << "	cause: " << cause << std::endl;
    }

    void delivery_complete(mqtt::delivery_token_ptr token) override {}

    void message_arrived(const mqtt::const_message_ptr msg) override
    {
        std::cout << "Message arrived: " << msg->get_payload_str() << std::endl;
    }

    void on_failure(const mqtt::token &tok) override
    {
        std::cout << "Connection attempt failed" << std::endl;
    }

    void on_success(const mqtt::token &tok) override
    {
        std::cout << "Connection attempt successful" << std::endl;

        // 发布消息
        mqtt::message_ptr pubmsg = mqtt::make_message(TOPIC, "Hello from Paho C++");
        pubmsg->set_qos(1);
        client_.publish(pubmsg);
    }
};

int main(int argc, char *argv[])
{
    char szT[128];
    mqtt::async_client client(SERVER_ADDRESS, CLIENT_ID);
    callback cb(client);
    client.set_callback(cb);
    mqtt::connect_options connOpts;
    connOpts.set_keep_alive_interval(60);  // 设置心跳间隔为60秒
    connOpts.set_clean_session(false);     // 设置为非清理会话模式

    try
    {
        std::cout << "Connecting to the MQTT server..." << std::endl;
        mqtt::token_ptr conntok = client.connect(connOpts);
        conntok->wait();

        std::cout << "Connected!" << std::endl;

        // 订阅消息
        client.subscribe(TOPIC, 1)->wait();

        size_t i = 0;
        while (true)
        {
            sprintf(szT, "%08d", i++);
            client.publish(TOPIC, szT, strlen(szT), QOS, false);
            std::this_thread::sleep_for(std::chrono::milliseconds(5));
        }
        client.disconnect()->wait();
    }
    catch (const mqtt::exception &exc)
    {
        std::cerr << "Error: " << exc.what() << std::endl;
        return 1;
    }

    return 0;
}